package br.com.edumobi.dados;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import br.com.edumobi.dados.modelos.Alternativa;
import br.com.edumobi.dados.modelos.Classificacao;
import br.com.edumobi.dados.modelos.Questao;
import br.com.edumobi.dados.modelos.Simulado;
import br.com.edumobi.dados.modelos.enuns.Nivel;
import br.com.edumobi.utils.Dates;

public class DadosLocal extends SQLiteOpenHelper implements IDadosLocal {

    private static final String DATABESE_NAME = "edumobi";
    private static final int VERSION = 1;

    public DadosLocal(Context contexto) {
        super(contexto, DATABESE_NAME, null, VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        StringBuilder SQL_CREATE_TABLE_CLASSIFICACOES = new StringBuilder()
                .append(" CREATE TABLE CLASSIFICACOES ( ")
                .append(" _id NUMERIC PRIMARY KEY ")
                .append(" , nome TEXT NOT NULL ")
                .append(" , descricao TEXT ")
                .append(" , classificacao_superior NUMERIC ")
                .append(" , FOREIGN KEY(classificacao_superior) REFERENCES CLASSIFICACOES(_id) ")
                .append(" ) ");

        StringBuilder SQL_CREATE_TABLE_QUESTOES = new StringBuilder()
                .append(" CREATE TABLE QUESTOES ( ")
                .append(" _id NUMERIC PRIMARY KEY ")
                .append(" , enunciado TEXT NOT NULL ")
                .append(" , observacao TEXT ")
                .append(" , imagem TEXT ")
                .append(" , classificacao NUMERIC NOT NULL ")
                .append(" , alternativa_correta NUMERIC NOT NULL ")
                .append(" , nivel NUMERIC NOT NULL ")
                .append(" , respondida NUMERIC ")
                .append(" , acertou NUMERIC ")
                .append(" , FOREIGN KEY(classificacao) REFERENCES CLASSIFICACOES(_id) ")
                .append(" , FOREIGN KEY(alternativa_correta) REFERENCES ALTERNATIVAS(_id) ")
                .append(" ) ");

        StringBuilder SQL_CREATE_TABLE_ALTERNATIVAS = new StringBuilder()
                .append(" CREATE TABLE ALTERNATIVAS ( ")
                .append(" _id NUMERIC PRIMARY KEY ")
                .append(" , alternativa TEXT NOT NULL ")
                .append(" , questao NUMERIC NOT NULL ")
                .append(" , FOREIGN KEY(questao) REFERENCES QUESTOES(_id) ")
                .append(" ) ");

        StringBuilder SQL_CREATE_TABLE_SIMULADOS = new StringBuilder()
                .append(" CREATE TABLE SIMULADOS ( ")
                .append(" _id NUMERIC PRIMARY KEY ")
                .append(" , titulo TEXT NOT NULL ")
                .append(" , descricao TEXT NOT NULL ")
                .append(" , classificacao NUMERIC NOT NULL ")
                .append(" , quantidade_de_questoes NUMERIC ")
                .append(" , duracao NUMERIC ")
                .append(" , FOREIGN KEY(classificacao) REFERENCES CLASSIFICACOES(_id) ")
                .append(" ) ");


        sqLiteDatabase.execSQL(SQL_CREATE_TABLE_CLASSIFICACOES.toString());
        sqLiteDatabase.execSQL(SQL_CREATE_TABLE_QUESTOES.toString());
        sqLiteDatabase.execSQL(SQL_CREATE_TABLE_ALTERNATIVAS.toString());
        sqLiteDatabase.execSQL(SQL_CREATE_TABLE_SIMULADOS.toString());
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i2) {

    }

    @Override
    public void inserirClassificacao(Classificacao classificacao) {
        ContentValues contentValues = new ContentValues();

        contentValues.put("_id", classificacao.id);
        contentValues.put("nome", classificacao.nome);
        contentValues.put("descricao", classificacao.descricao);

        if (classificacao.classificacaoSuperior != null) {
            contentValues.put("classificacao_superior", classificacao.classificacaoSuperior.id);
        }

        getWritableDatabase().insert("CLASSIFICACOES", null, contentValues);

        if (classificacao.questoes != null) {
            for (Questao questao : classificacao.questoes) {
                inserirQuestao(questao, classificacao);
            }
        }
    }

    @Override
    public void alterarClassificacao(Classificacao classificacao) {
        ContentValues contentValues = new ContentValues();
        contentValues.put("nome", classificacao.nome);
        contentValues.put("descricao", classificacao.descricao);

        if (classificacao.classificacaoSuperior != null) {
            contentValues.put("classificacao_superior", classificacao.classificacaoSuperior.id);
        }

        String where = "_id = ?";
        String argumentos[] = {classificacao.id.toString()};

        getWritableDatabase().update("CLASSIFICACOES", contentValues, where, argumentos);
    }

    @Override
    public void removerClassificacao(Classificacao classificacao) {
        String where = "_id = ?";
        String argumentos[] = {classificacao.id.toString()};

        getWritableDatabase().delete("CLASSIFICACOES", where, argumentos);
    }

    @Override
    public Classificacao consultarClassificacaoPorId(Long id) {

        Cursor cursor = getReadableDatabase().rawQuery("SELECT * FROM CLASSIFICACOES WHERE _id = ?", new String[]{id.toString()});

        Classificacao classificacao = null;

        while (cursor.moveToNext()) {

             classificacao = new Classificacao(
                    cursor.getLong(cursor.getColumnIndex("_id")),
                    cursor.getString(cursor.getColumnIndex("nome")),
                    cursor.getString(cursor.getColumnIndex("descricao")),
                    consultarClassificacaoPorId(cursor.getLong(cursor.getColumnIndex("classificacao_superior"))),
                    null
            );

            classificacao.questoes = consultarQuestoesPorClassificacao(classificacao);

        }

        return classificacao;
    }

    @Override
    public List<Classificacao> consultarClassificacoes() {

        List<Classificacao> classificacoes = new ArrayList<Classificacao>();

        Cursor cursor = getReadableDatabase().rawQuery("SELECT * FROM CLASSIFICACOES", null);

        while (cursor.moveToNext()) {

            Classificacao classificacao = new Classificacao(
                    cursor.getLong(cursor.getColumnIndex("_id")),
                    cursor.getString(cursor.getColumnIndex("nome")),
                    cursor.getString(cursor.getColumnIndex("descricao")),
                    consultarClassificacaoPorId(cursor.getLong(cursor.getColumnIndex("classificacao_superior"))),
                    null
            );

            classificacao.questoes = consultarQuestoesPorClassificacao(classificacao);

            classificacoes.add(classificacao);
        }

        return classificacoes;
    }

    @Override
    public List<Classificacao> consultarClassificacoesPorClassificacaoSuperior(Classificacao classificacaoSuperior) {
        List<Classificacao> classificacoes = new ArrayList<Classificacao>();

        Cursor cursor;

        if (classificacaoSuperior != null) {
            cursor = getReadableDatabase().rawQuery("SELECT * FROM CLASSIFICACOES WHERE classificacao_superior = ?", new String[]{classificacaoSuperior.id.toString()});
        } else {
            cursor = getReadableDatabase().rawQuery("SELECT * FROM CLASSIFICACOES WHERE classificacao_superior is null", null);
        }

        while (cursor.moveToNext()) {

            Classificacao classificacao = new Classificacao(
                    cursor.getLong(cursor.getColumnIndex("_id")),
                    cursor.getString(cursor.getColumnIndex("nome")),
                    cursor.getString(cursor.getColumnIndex("descricao")),
                    classificacaoSuperior,
                    null
            );

            classificacao.questoes = consultarQuestoesPorClassificacao(classificacao);

            classificacoes.add(classificacao);
        }

        return classificacoes;
    }

    @Override
    public void inserirQuestao(Questao questao, Classificacao classificacao) {
        ContentValues contentValues = new ContentValues();
        contentValues.put("_id", questao.id);
        contentValues.put("enunciado", questao.enunciado);
        contentValues.put("classificacao", classificacao.id);
        contentValues.put("alternativa_correta", questao.alternativaCorreta.id);
        contentValues.put("nivel", questao.nivel.id);
        contentValues.put("respondida", questao.respondida ? 1 : 0);
        contentValues.put("acertou", questao.acertou ? 1 : 0);

        if (questao.observacao != null) {
            contentValues.put("observacao", questao.observacao);
        }

        if (questao.imagem != null) {
            contentValues.put("imagem", questao.imagem);
        }

        getWritableDatabase().insert("QUESTOES", null, contentValues);

        for (Alternativa alternativa : questao.alternativas) {
            inserirAlternativa(alternativa, questao);
        }
    }

    @Override
    public void alterarQuestao(Questao questao, Classificacao classificacao) {
        ContentValues contentValues = new ContentValues();
        contentValues.put("enunciado", questao.enunciado);
        contentValues.put("classificacao", classificacao.id);
        contentValues.put("alternativa_correta", questao.alternativaCorreta.id);
        contentValues.put("nivel", questao.nivel.id);
        contentValues.put("respondida", questao.respondida ? 1 : 0);
        contentValues.put("acertou", questao.acertou ? 1 : 0);

        if (questao.observacao != null) {
            contentValues.put("observacao", questao.observacao);
        }

        if (questao.imagem != null) {
            contentValues.put("imagem", questao.imagem);
        }

        String where = "_id = ?";
        String argumentos[] = {questao.id.toString()};

        getWritableDatabase().update("QUESTOES", contentValues, where, argumentos);
    }

    @Override
    public void removerQuestao(Questao questao) {
        String where = "_id = ?";
        String argumentos[] = {questao.id.toString()};

        getWritableDatabase().delete("QUESTOES", where, argumentos);
    }

    @Override
    public Questao consultarQuestaoPorId(Long id) {
        Cursor cursor = getReadableDatabase().rawQuery("SELECT * FROM QUESTOES WHERE _id = ?", new String[]{id.toString()});

        Questao questao = null;

        while (cursor.moveToNext()) {
            questao = new Questao(
                    cursor.getLong(cursor.getColumnIndex("_id")),
                    cursor.getString(cursor.getColumnIndex("enunciado")),
                    cursor.getString(cursor.getColumnIndex("observacao")),
                    cursor.getString(cursor.getColumnIndex("imagem")),
                    consultarAlternativaPorId(cursor.getLong(cursor.getColumnIndex("alternativa_correta"))),
                    null,
                    Nivel.getEnum(cursor.getInt(cursor.getColumnIndex("nivel")))
            );
            questao.alternativas = consultarAlternativaPorQuestao(questao);
            questao.respondida = cursor.getInt(cursor.getColumnIndex("respondida")) == 1;
            questao.acertou = cursor.getInt(cursor.getColumnIndex("acertou")) == 1;
        }

        return questao;
    }

    @Override
    public List<Questao> consultarQuestoes() {
        List<Questao> questoes = new ArrayList<Questao>();

        Cursor cursor = getReadableDatabase().rawQuery("SELECT * FROM QUESTOES ORDER BY _id ASC", null);

        while (cursor.moveToNext()) {
            Questao questao = new Questao(
                    cursor.getLong(cursor.getColumnIndex("_id")),
                    cursor.getString(cursor.getColumnIndex("enunciado")),
                    cursor.getString(cursor.getColumnIndex("observacao")),
                    cursor.getString(cursor.getColumnIndex("imagem")),
                    consultarAlternativaPorId(cursor.getLong(cursor.getColumnIndex("alternativa_correta"))),
                    null,
                    Nivel.getEnum(cursor.getInt(cursor.getColumnIndex("nivel")))
            );

            questao.alternativas = consultarAlternativaPorQuestao(questao);
            questao.respondida = cursor.getInt(cursor.getColumnIndex("respondida")) == 1;
            questao.acertou = cursor.getInt(cursor.getColumnIndex("acertou")) == 1;

            questoes.add(questao);
        }

        return questoes;
    }

    @Override
    public List<Questao> consultarQuestoesPorClassificacao(Classificacao classificacao) {
        List<Questao> questoes = new ArrayList<Questao>();

        Cursor cursor = getReadableDatabase().rawQuery("SELECT * FROM QUESTOES WHERE classificacao = ? ORDER BY _id ASC", new String[]{classificacao.id.toString()});

        while (cursor.moveToNext()) {
            Questao questao = new Questao(
                    cursor.getLong(cursor.getColumnIndex("_id")),
                    cursor.getString(cursor.getColumnIndex("enunciado")),
                    cursor.getString(cursor.getColumnIndex("observacao")),
                    cursor.getString(cursor.getColumnIndex("imagem")),
                    consultarAlternativaPorId(cursor.getLong(cursor.getColumnIndex("alternativa_correta"))),
                    null,
                    Nivel.getEnum(cursor.getInt(cursor.getColumnIndex("nivel")))
            );

            questao.alternativas = consultarAlternativaPorQuestao(questao);
            questao.respondida = cursor.getInt(cursor.getColumnIndex("respondida")) == 1;
            questao.acertou = cursor.getInt(cursor.getColumnIndex("acertou")) == 1;

            questoes.add(questao);
        }

        return questoes;

    }

    @Override
    public void inserirAlternativa(Alternativa alternativa, Questao questao) {
        ContentValues contentValues = new ContentValues();
        contentValues.put("_id", alternativa.id);
        contentValues.put("alternativa", alternativa.alternativa);
        contentValues.put("questao", questao.id);

        getWritableDatabase().insert("ALTERNATIVAS", null, contentValues);
    }

    @Override
    public void alterarAlternativa(Alternativa alternativa, Questao questao) {
        ContentValues contentValues = new ContentValues();
        contentValues.put("alternativa", alternativa.alternativa);
        contentValues.put("questao", questao.id);

        String where = "_id = ?";
        String argumentos[] = {alternativa.id.toString()};

        getWritableDatabase().update("ALTERNATIVAS", contentValues, where, argumentos);
    }

    @Override
    public void removerAlternativa(Alternativa alternativa) {
        String where = "_id = ?";
        String argumentos[] = {alternativa.id.toString()};

        getWritableDatabase().delete("ALTERNATIVAS", where, argumentos);
    }

    @Override
    public Alternativa consultarAlternativaPorId(Long id) {
        Cursor cursor = getReadableDatabase().rawQuery("SELECT * FROM ALTERNATIVAS WHERE _id = ?", new String[]{id.toString()});

        Alternativa alternativa = null;

        while (cursor.moveToNext()) {
            alternativa = new Alternativa(
                    cursor.getLong(cursor.getColumnIndex("_id")),
                    cursor.getString(cursor.getColumnIndex("alternativa"))
            );
        }

        return alternativa;
    }

    @Override
    public List<Alternativa> consultarAlternativas() {

        List<Alternativa> alternativas = new ArrayList<Alternativa>();

        Cursor cursor = getReadableDatabase().rawQuery("SELECT * FROM ALTERNATIVAS", null);

        while (cursor.moveToNext()) {
            Alternativa alternativa = new Alternativa(
                    cursor.getLong(cursor.getColumnIndex("_id")),
                    cursor.getString(cursor.getColumnIndex("alternativa"))
            );

            alternativas.add(alternativa);
        }

        return alternativas;
    }

    @Override
    public List<Alternativa> consultarAlternativaPorQuestao(Questao questao) {

        List<Alternativa> alternativas = new ArrayList<Alternativa>();

        Cursor cursor = getReadableDatabase().rawQuery("SELECT * FROM ALTERNATIVAS WHERE questao = ?", new String[]{questao.id.toString()});

        while (cursor.moveToNext()) {
            Alternativa alternativa = new Alternativa(
                    cursor.getLong(cursor.getColumnIndex("_id")),
                    cursor.getString(cursor.getColumnIndex("alternativa"))
            );

            alternativas.add(alternativa);
        }

        return alternativas;
    }

    @Override
    public void inserirSimulado(Simulado simulado) {
        ContentValues contentValues = new ContentValues();
        contentValues.put("_id", simulado.id);
        contentValues.put("titulo", simulado.titulo);
        contentValues.put("descricao", simulado.descricao);
        contentValues.put("quantidade_de_questoes", simulado.quantidadeDeQuestoes);
        contentValues.put("classificacao", simulado.classificacao.id);

        if (simulado.duracao != null) {
            contentValues.put("duracao", simulado.duracao.getTime());
        }

        getWritableDatabase().insert("SIMULADOS", null, contentValues);
    }

    @Override
    public void alterarSimulado(Simulado simulado) {
        ContentValues contentValues = new ContentValues();
        contentValues.put("titulo", simulado.titulo);
        contentValues.put("descricao", simulado.descricao);
        contentValues.put("quantidade_de_questoes", simulado.quantidadeDeQuestoes);
        contentValues.put("classificacao", simulado.classificacao.id);

        if (simulado.duracao != null) {
            contentValues.put("duracao", simulado.duracao.getTime());
        }

        String where = "_id = ?";
        String argumentos[] = {simulado.id.toString()};

        getWritableDatabase().update("SIMULADOS", contentValues, where, argumentos);
    }

    @Override
    public void removerSimulado(Simulado simulado) {
        String where = "_id = ?";
        String argumentos[] = {simulado.id.toString()};

        getWritableDatabase().delete("SIMULADOS", where, argumentos);
    }

    @Override
    public Simulado consultarSimuladoPorId(Long id) {
        Cursor cursor = getReadableDatabase().rawQuery("SELECT * FROM SIMULADOS WHERE _id = ?", new String[]{id.toString()});

        Simulado simulado = null;

        while (cursor.moveToNext()) {
            simulado = new Simulado(
                    cursor.getLong(cursor.getColumnIndex("_id")),
                    cursor.getString(cursor.getColumnIndex("titulo")),
                    cursor.getString(cursor.getColumnIndex("descricao")),
                    consultarClassificacaoPorId(cursor.getLong(cursor.getColumnIndex("classificacao"))),
                    cursor.getInt(cursor.getColumnIndex("quantidade_de_questoes")),
                    new Date()
            );

            simulado.duracao.setTime(cursor.getLong(cursor.getColumnIndex("duracao")));
        }

        return simulado;
    }

    @Override
    public List<Simulado> consultarSimuladosPorClassificacao(Classificacao classificacao) {
        Cursor cursor = getReadableDatabase().rawQuery("SELECT * FROM SIMULADOS WHERE classificacao = ?", new String[]{classificacao.id.toString()});

        List<Simulado> simulados = new ArrayList<Simulado>();

        while (cursor.moveToNext()) {
            Simulado simulado = new Simulado(
                    cursor.getLong(cursor.getColumnIndex("_id")),
                    cursor.getString(cursor.getColumnIndex("titulo")),
                    cursor.getString(cursor.getColumnIndex("descricao")),
                    consultarClassificacaoPorId(cursor.getLong(cursor.getColumnIndex("classificacao"))),
                    cursor.getInt(cursor.getColumnIndex("quantidade_de_questoes")),
                    new Date()
            );

            simulado.duracao.setTime(cursor.getLong(cursor.getColumnIndex("duracao")));

            simulados.add(simulado);
        }

        return simulados;
    }
}